<?php
namespace app\common\lib;

use Qiniu\Auth;
use Qiniu\Processing\ImageUrlBuilder;
use Qiniu\Storage\UploadManager;
use Qiniu\Storage\BucketManager;
class Qiniu{

    private $_config = array(
        'secretKey' => '', //七牛密码
        'accessKey' => '', //七牛用户
        'domain' => '', //七牛服务器
        'protocol' => '',
        'bucket' => '', //空间名称
        'timeout' => 300, //超时时间
        'maxSize' => 5120, //文件大小(KB)
        'exts' => 'bmp,png,gif,jpeg,jpg',
        'rootPath' => './',
        'list' => '' //存储目录 
    );

    private $_error = 0;
    protected $_auth;
    public function __construct($config = [])
    {
        $this->_config = array(
            'secretKey' => $config['secret_key'], //七牛密码
            'accessKey' => $config['access_key'], //七牛用户
            'domain' => $config['domain'], //七牛服务器
            'protocol' => $config['protocol'],
            'bucket' => $config['bucket'], //空间名称
            'saveNameRule' => array('uniqid', ''),
            'timeout' => 300,
            'maxSize' => $config['fileupload_size'],
            'exts' => 'bmp,png,gif,jpeg,jpg',
        );
        $this->_config['maxSize'] = $this->_config['maxSize'] * 1024;
        if(!empty($config['list'])){
            $this->_config['list'] = $config['list'];
        }

        $this->_auth = new Auth(
            $this->_config['accessKey'],
            $this->_config['secretKey']
        );

    }

    public function upload( $file, $filename = '', $width = '', $height = '', $thumb = false){
        //调用前 就判断文件大小，允许上传的类型
        //tp6 使用的 think-filesystem 获取值改变
        $token = $this->_auth->uploadToken($this->_config['bucket']);
        $uploadMgr = new UploadManager();
        $filename = $filename ? $filename : $this->getSaveName($file->getOriginalName());
        if(!empty($this->_config['list'])){
            $filename = $this->_config['list'].'/'.$filename;
        }
        // 调用 UploadManager 的 putFile 方法进行文件的上传。
        list($ret, $err) = $uploadMgr->putFile($token,$filename,$file->getPathname());
        if ($err !== null) {
            $this->_error = $err->message();
            return false;
        } else {
            if ($thumb) {
                return $this->makeThumb(
                    $this->downLink($ret['key']),
                    $width,
                    $height
                );
            } else {
                return $this->downLink($ret['key']);
            }
        }
    }



    /**
     * 上传文件 - 二进制
     */
    public function uploadStream($file,$filename = '',$width = '',$height = '',$thumb = false){
        $uploadMgr = new UploadManager();
        $token = $this->_auth->uploadToken($this->_config['bucket']);
        if(!empty($this->_config['list'])){
            $filename = $this->_config['list'].'/'.$filename;
        }
        list($ret, $err) = $uploadMgr->put($token, $filename, $file);
        if ($err !== null) {
            $this->_error = $err->message();
            return false;
        } else {
            if ($thumb) {
                return $this->makeThumb(
                    $this->downLink($ret['key']),
                    $width,
                    $height
                );
            } else {
                return $this->downLink($ret['key']);
            }
        }
    }

    public function delete($file)
    {
        $file = str_replace(
            $this->_config['protocol'] . $this->_config['domain'] . '/',
            '',
            $file
        );
        //初始化BucketManager
        $bucketMgr = new BucketManager($this->_auth);
        $err = $bucketMgr->delete($this->_config['bucket'], $file);
        if ($err !== null) {
            $this->_error = $err;
            return false;
        } else {
            return true;
        }
    }

    public function getKey($url)
    {
        $url = str_replace(
            $this->_config['protocol'] . $this->_config['domain'] . '/',
            '',
            $url
        );
        return $url;
    }

    /**
     * 生成缩略图url
     */
    public function getThumbName($url, $width, $height)
    {
        $url = str_replace(
            $this->_config['protocol'] . $this->_config['domain'] . '/',
            '',
            $url
        );
        $arr = explode('.', $url);
        return $arr[0] . '_' . $width . 'x' . $height . '.' . $arr[1];
    }

    /**
     * 根据指定的规则获取文件或目录名称
     * @param  array  $rule     规则
     * @param  string $filename 原文件名
     * @return string           文件或目录名称
     */
    private function getName($rule, $filename)
    {
        $name = '';
        if (is_array($rule)) {
            //数组规则
            $func = $rule[0];
            $param = (array) $rule[1];
            foreach ($param as &$value) {
                $value = str_replace('__FILE__', $filename, $value);
            }
            $name = call_user_func_array($func, $param);
        } elseif (is_string($rule)) {
            //字符串规则
            if (function_exists($rule)) {
                $name = call_user_func($rule);
            } else {
                $name = $rule;
            }
        }
        return $name;
    }
    /**
     * 根据上传文件命名规则取得保存文件名
     * @param string $file 文件信息
     */
    private function getSaveName($name)
    {
        $rule = $this->_config['saveNameRule'];
        if (empty($rule)) {
            //保持文件名不变
            /* 解决pathinfo中文文件名BUG */
            $filename = substr(
                pathinfo("_{$name}", PATHINFO_FILENAME),
                1
            );
            $savename = $filename;
        } else {
            $savename = $this->getName($rule, $name);
            if (empty($savename)) {
                $this->_error = '文件命名规则错误！';
                return false;
            }
        }
        /* 获取上传文件后缀，允许上传无后缀文件 */
        $ext = pathinfo($name, PATHINFO_EXTENSION);
        return date('Y-m-d-') . $savename . '.' . $ext;
    }

    //获取文件下载资源链接
    public function downLink($key)
    {
        $key = urlencode($key);
        $key = self::_escapeQuotes($key);
        $url = $key;
        return $url;
    }

    public function makeThumb($url, $width, $height)
    {
        $imageUrlBuilder = new ImageUrlBuilder();
        $thumbLink = $imageUrlBuilder->thumbnail($url, 1, $width, $height);
        return $thumbLink;
    }

    static function _escapeQuotes($str)
    {
        $find = array('\\', "\"");
        $replace = array('\\\\', "\\\"");
        return str_replace($find, $replace, $str);
    }

    public function getError()
    {
        return $this->_error;
    }
    /**
     * 检查上传的文件
     * @param array $file 文件信息
     */
    private function check($file)
    {
        /* 文件上传失败，捕获错误代码 */
        if ($file['error']) {
            $this->_error = '文件上传失败';
            return false;
        }

        /* 无效上传 */
        if (empty($file['name'])) {
            $this->_error = '未知上传错误！';
            return false;
        }

        /* 检查是否合法上传 */
        if (!is_uploaded_file($file['tmp_name'])) {
            $this->_error = '非法上传文件！';
            return false;
        }

        /* 检查文件大小 */
        if (!$this->checkSize($file['size'])) {
            $this->_error = '上传文件大小不符！';
            return false;
        }

        /* 检查文件Mime类型 */
        //TODO:FLASH上传的文件获取到的mime类型都为application/octet-stream
        if (!$this->checkMime($file['type'])) {
            $this->_error = '上传文件MIME类型不允许！';
            return false;
        }

        /* 检查文件后缀 */
        if (!$this->checkExt($file['ext'])) {
            $this->_error = '上传文件后缀不允许';
            return false;
        }

        /* 通过检测 */
        return true;
    }
    /**
     * 检查文件大小是否合法
     * @param integer $size 数据
     */
    private function checkSize($size)
    {
        return !($size > $this->_config['maxSize']) ||
            0 == $this->_config['maxSize'];
    }

    /**
     * 检查上传的文件MIME类型是否合法
     * @param string $mime 数据
     */
    private function checkMime($mime)
    {
        return empty($this->_config['mimes'])
            ? true
            : in_array(strtolower($mime), explode(',', $this->_config['mimes']));
    }

    /**
     * 检查上传的文件后缀是否合法
     * @param string $ext 后缀
     */
    private function checkExt($ext)
    {
        return empty($this->_config['exts'])
            ? true
            : in_array(strtolower($ext), explode(',', $this->_config['exts']));
    }

    public function qiniu_url($key){
        return $this->_config['protocol'] . $this->_config['domain'] . '/'.$key;
    }

}